/*
 * Copyright (c) 2008, Xiong Yingfei, the University of Tokyo All rights
 * reserved.
 */
package ac.jp.u_tokyo.SyncLib.tests;

import org.antlr.runtime.RecognitionException;
import org.junit.Test;
import static org.junit.Assert.*;

import ac.jp.u_tokyo.SyncLib.IDSync;
import ac.jp.u_tokyo.SyncLib.Mod;
import ac.jp.u_tokyo.SyncLib.Sync;
import ac.jp.u_tokyo.SyncLib.SyncFactory;
import ac.jp.u_tokyo.SyncLib.SynchronizationFailedException;
import ac.jp.u_tokyo.SyncLib.Value2Mod;
import ac.jp.u_tokyo.SyncLib.dictionaries.DynamicGet;
import ac.jp.u_tokyo.SyncLib.dictionaries.InsertNewKeyDynamicGet;
import ac.jp.u_tokyo.SyncLib.dictionaries.MaxIntegerKeyFactory;
import ac.jp.u_tokyo.SyncLib.graphCombinator.GraphCombinator;
import ac.jp.u_tokyo.SyncLib.graphCombinator.GraphCombinatorFactory;
import ac.jp.u_tokyo.SyncLib.modParser.ModParser;
import ac.jp.u_tokyo.SyncLib.util.Helper;
import ac.jp.u_tokyo.SyncLib.valueParser.ValueParser;

public class GraphCombinatorTest
{

//	@Test
//	public void testSimpleAdd() throws SynchronizationFailedException
//	{
//		AddConst addConst = new AddConst(2);
//		Mod mod1 = new PrimMod<Integer>(2);
//		List<Mod> modList = new ArrayList<Mod>(2);
//		modList.add(mod1);
//		modList.add(null);
//		modList = addConst.synchronize(modList);
//		modList = addConst.synchronize(modList);
//		
//		Helper.assertPrimitiveModList(modList, 2, 4);
////		assertEquals(2, ((PrimMod<Integer>) modList.get(0))
////				.getNewValue());
////		assertEquals(4, ((PrimMod<Integer>) modList.get(1))
////				.getNewValue());
//	}
//
//	@Test
//	public void testSingleContainedGraph()
//			throws SynchronizationFailedException
//	{
//		GraphCombinator gc = create();
//
//		List<Mod> modList = Helper
//				.toArrayList(
//						(Mod) new PrimMod<Integer>(
//								2), null);
//		modList = gc.synchronize(modList);
//		modList = gc.synchronize(modList);
//		Helper.assertPrimitiveModList(modList, 2, 5);
////		assertEquals(2, modList.size());
////		assertEquals(2, ((PrimMod<Integer>) modList.get(0))
////				.getNewValue());
////		assertEquals(5, ((PrimMod<Integer>) modList.get(1))
////				.getNewValue());
//
//	}
//
//	private GraphCombinator create()
//	{
//		GraphCombinatorFactory f = new GraphCombinatorFactory();
//		f.setParaVars("a", "c");
//		f.setOtherVars("b");
//		f.connectSync(new SyncFactory() {
//
//			public Sync create() {
//				return new AddConst(1);
//			}
//			
//		}, "a", "b");
//		f.connectSync(new SyncFactory() {
//
//			public Sync create() {
//				return new AddConst(2);
//			}
//			
//		} , "b", "c");
//
//		GraphCombinator gc = f.create();
//		return gc;
//	}
//
//	@Test(expected = SynchronizationFailedException.class)
//	public void testFail() throws SynchronizationFailedException
//	{
//		GraphCombinator gc = create();
//
//		List<Mod> modList = Helper.toArrayList(
//				(Mod) new PrimMod<Integer>(2),
//				new PrimMod<Integer>(3));
//		modList = gc.synchronize(modList);
//	}
//
//	@Test
//	public void testRecover() throws SynchronizationFailedException
//	{
//		GraphCombinator gc = create();
//
//		List<Mod> modList = Helper.toArrayList(
//				(Mod) new PrimMod<Integer>(100),
//				new PrimMod<Integer>(106));
//		try
//		{
//			modList = gc.synchronize(modList);
//			fail();
//		}
//		catch (SynchronizationFailedException e)
//		{
//			modList = Helper.toArrayList(null,
//					(Mod) new PrimMod<Integer>(3));
//			modList = gc.synchronize(modList);
//			modList = gc.synchronize(modList);
//			Helper.assertPrimitiveModList(modList, 0, 3);
////			assertEquals(2, modList.size());
////			assertEquals(0, ((PrimMod<Integer>) modList
////					.get(0)).getNewValue());
////			assertEquals(3, ((PrimMod<Integer>) modList
////					.get(1)).getNewValue());
//		}
//	}
//
//	@Test
//	public void testPriority() throws SynchronizationFailedException
//	{
//		GraphCombinatorFactory f = new GraphCombinatorFactory();
//		f.setParaVars("a", "b", "x", "y");
//		f.setOtherVars("c");
//		f.connectSync(new SyncFactory() {
//
//			public Sync create() {
//				return new Add();
//			}
//			
//		}, "a", "b", "y");
//		f.connectSync(new SyncFactory() {
//
//			public Sync create() {
//				return new AddConst(1);
//			}
//			
//		}, "a", "c");
//		f.connectSync(new SyncFactory() {
//
//			public Sync create() {
//				return new AddConst(2);
//			}
//			
//		}, "c", "x");
//
//		GraphCombinator gc = f.create();
//
//		List<Mod> modList =
//			Helper.createPrimitiveModList(null, null, 5, 10);
//		modList = gc.synchronize(modList);
//		modList = gc.synchronize(modList);
//
//		Helper.assertPrimitiveModList(modList, 2, 8, 5, 10);
//
//	}
	
	@Test
	public void twoIDTest() throws SynchronizationFailedException {
		GraphCombinatorFactory f = new GraphCombinatorFactory();
		f.setParaVars("v1", "v2", "v3");
		SyncFactory idFactory = new SyncFactory() {
			public Sync create() {
				return new IDSync(true);
			}
		};
		f.connectSync(idFactory, "v1", "v2");
		f.connectSync(idFactory, "v1", "v3");
		GraphCombinator sync = f.create();
		Mod[] result = sync.synchronize(Helper.createPrimitiveModList(1, null, null));
		Helper.assertPrimitiveModList(result, 1, 1, 1);
	}
	
	@Test
	public void twoIDResyncTest() throws SynchronizationFailedException, RecognitionException {
		GraphCombinatorFactory f = new GraphCombinatorFactory();
		f.setParaVars("v1", "v2", "v3");
		SyncFactory idFactory = new SyncFactory() {
			public Sync create() {
				return new IDSync(true);
			}
		};
		f.connectSync(idFactory, "v1", "v2");
		f.connectSync(idFactory, "v2", "v3");
		GraphCombinator sync = f.create();
		Mod[] result = sync.resynchronize(ValueParser.parse("a, b, c"),
				Helper.createPrimitiveModList(null, null, 1));
		Helper.assertPrimitiveModList(result, 1, 1, 1);
		
		result = sync.resynchronize(ValueParser.parse("a, b, c"),
				Helper.createPrimitiveModList(null, null, null));
		Helper.assertPrimitiveModList(result, "a", "a", "a");

	}
	
	@Test
	public void IDGetResyncTest() throws SynchronizationFailedException, RecognitionException {
		GraphCombinatorFactory f = new GraphCombinatorFactory();
		f.setParaVars("v1", "v2", "v3");
		f.setOtherVars("v");
		SyncFactory idFactory = new SyncFactory() {
			public Sync create() {
				return new IDSync(true);
			}
		};
		SyncFactory getFactory = new SyncFactory() {
			public Sync create() {
				return new InsertNewKeyDynamicGet(true, new MaxIntegerKeyFactory());
			}
		};

		f.connectSync(idFactory, "v2", "v");
		f.connectSync(getFactory, "v1", "v", "v3");
		GraphCombinator sync = f.create();
		Mod[] result = sync.resynchronize(ValueParser.parse("1, {10->a, 20->b}, b"),
				ModParser.parse("nomod, nomod, b"));
		
		Mod[] expected = ModParser.parse("20, {20->b}, b");
		for(int i = 0; i < result.length; i++) {
			assertEquals(result[i], result[i].merge(expected[i]));
		}

	}



}
